package net.sf.rose.business.action;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.rose.business.bean.action.Action;
import net.sf.rose.business.bean.control.MenuBean;
import net.sf.rose.business.bean.database.TableMetaBean;
import net.sf.rose.business.service.ActionService;
import net.sf.rose.business.service.DataBaseService;
import net.sf.rose.business.service.MenuSevice;
import net.sf.rose.exception.SystemErrorCode;
import net.sf.rose.exception.SystemException;
import net.sf.rose.jdbc.DBUtils;
import net.sf.rose.jdbc.GenericDAO;
import net.sf.rose.jdbc.PageBean;
import net.sf.rose.jdbc.QueryMapSQL;
import net.sf.rose.jdbc.service.Service;
import net.sf.rose.web.WebUtils;
import net.sf.rose.web.spring.servlet.handler.FormConvert;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author fengjian
 * @since 2014/02/01
 */
@Controller
@RequestMapping("/common")
public class CommonController {

	/**
	 * 功能：根据传入的jsp参数直接返回视图。
	 * 同时将请求参数一并带过去，保证页面跳转时不会丢失数据。
	 * @param jsp 	- 视图名称
	 */
	@RequestMapping("/view.html")
	public ModelAndView view(HttpServletRequest request, String jsp) {
		if (jsp == null || jsp.equals("")) {
			throw new SystemException("Action参数缺失！，jsp不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		FormConvert form = new FormConvert();
		return new ModelAndView(jsp, form.convertRequest(request));
	}

	/**
	 * 功能：根据传入的Menu名称，从配置文件中调取并执行它
	 * @param request       - Http请求
	 * @param response     - Http返回
	 * @param service        - 数据库连接服务类
	 * @param name          - 定义的Menu名称
	 */
	@RequestMapping("/menu.html")
	public ModelAndView menu(HttpServletRequest request, HttpServletResponse response, Service service, String name) {
		if (name == null || name.equals("")) {
			throw new SystemException("Menu参数缺失！，name不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		MenuBean menu = MenuSevice.getService().getMenuBean(name);
		if (menu == null) {
			throw new SystemException("名称为：" + name + "的Menu没有还配置。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		Map<String, Object> map = null;
		Map<String, Object> data = new HashMap<String, Object>();
		data.put(WebUtils.SYSTEM_USER, WebUtils.getUser(request));
		data.put(WebUtils.SYSTEM_USER, WebUtils.getSystemTime());
		// 根据名称查找定义的action处理
		Action action = ActionService.getAction(menu.getActionName());
		// 如果需要执行处理
		if (action != null) {
			// 保存前台提交的数据
			FormConvert form = new FormConvert();
			map = form.convertRequest(request);
			map.putAll(data);
			// 执行处理
			action.execute(request, response, service, map, data);
		}
		ModelAndView mav = null;
		// 如果返回提示消息
		if (menu.getOpenType().equals(MenuBean.OPEN_MESSAGE_TYPE)) {
			mav = new ModelAndView("ajaxDone");
			mav.addObject("statusCode", 200);
			mav.addObject("message", "操作成功！");
			mav.addObject("callbackType", true);
		} else {
			// 生成返回JSP页模型
			mav = new ModelAndView(menu.getView());
			// 将前台提交的数据加载到页面模型中
			mav.addAllObjects(map);
			// 将处理过程缓存数据加载到页面模型中
			mav.addAllObjects(data);
		}
		return mav;
	}

	/**
	 * 功能：根据传入的Action名称，从配置文件中调取操作集执行它
	 * @param request      - Http请求
	 * @param response    - Http返回
	 * @param service        - 数据库连接服务类
	 * @param name         - 定义的Action名称
	 * @param jsp              - 本操作执行完成后返回的JSP文件全路径名称，此值允许为空值；空值时返回JSON格式结果数据。
	 */
	@RequestMapping("/action.html")
	public ModelAndView action(HttpServletRequest request, HttpServletResponse response, Service service, 
			String name, @RequestParam(value = "jsp", required = false) String jsp) {
		if (name == null || name.equals("")) {
			throw new SystemException("Action参数缺失！，name不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		try {
			name = java.net.URLDecoder.decode(name, "UTF-8");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		// 根据名称查找定义的action处理
		Action action = ActionService.getAction(name);
		if (action == null) {
			throw new SystemException("名称为：" + name + "的Action没有还配置。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		// 保存前台提交的数据
		FormConvert form = new FormConvert();
		Map<String, Object> map = form.convertRequest(request);
		// 保存处理过程中的数据
		Map<String, Object> data = new HashMap<String, Object>();
		data.put(WebUtils.SYSTEM_USER, WebUtils.getUser(request));
		data.put(WebUtils.SYSTEM_NOW_TIME, WebUtils.getSystemTime());
		map.putAll(data);
		// 执行处理
		action.execute(request, response, service, map, data);
		service.commit();
		// 生成返回JSP页模型
		ModelAndView mav = null;
		if (jsp == null) {
			mav = new ModelAndView("ajaxDone");
			mav.addObject("statusCode", 200);
			mav.addObject("message", "操作成功！");
			mav.addObject("callbackType", true);
		} else {
			// 生成返回JSP页模型
			mav = new ModelAndView(jsp);
			// 将前台提交的数据加载到页面模型中
			mav.addAllObjects(map);
			// 将处理过程缓存数据加载到页面模型中
			mav.addAllObjects(data);
		}
		return mav;
	}

	/**
	 * 根据传入参数，执行数据库查询操作
	 * 1.参数sql和tableName这两个参数必须提供一个。
	 * 2.tableAction是数据库查询操作的几个常量，包括：load：查找单条记录；list：查找列表记录；page：分页查找列表记录；map：将查找结果根据主键存入Map类中；
	 * @param request        - Http请求
	 * @param service 		    - 数据库连接服务类
	 * @param sql			    - 执行数据库操作的查询语句
	 * @param tableName  - 需要执行数据库查询操作的数据库表名
	 * @param tableAction - 执行数据库查询操作的分类
	 * @param jsp			    - 本操作执行完成后返回的JSP文件全路径名称
	 */
	@RequestMapping("/search.html")
	public ModelAndView search(HttpServletRequest request, Service service, 
			@RequestParam(value = "sql", required = false) String sql,
			@RequestParam(value = "tableName", required = false) String tableName, 
			String tableAction, 
			String jsp) {
		if (tableName == null && sql == null) {
			throw new SystemException("Action参数缺失！，tableName或sql不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		if (tableAction == null || tableAction.equals("")) {
			throw new SystemException("Action参数缺失！，tableAction不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		if (jsp == null || jsp.equals("")) {
			throw new SystemException("Action参数缺失！，jsp不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		FormConvert form = new FormConvert();
		Map<String, Object> map = form.convertRequest(request);
		QueryMapSQL query = new QueryMapSQL(service);
		GenericDAO dao = new GenericDAO(service);
		ModelAndView mav = new ModelAndView(jsp);
		if (tableName != null) {
			map.put(QueryMapSQL.DEF_SYS_TABLE, tableName);
		} else if (sql == null) {
			map.put(QueryMapSQL.DEF_SYS_SQL, sql);
		}
		map.put(WebUtils.SYSTEM_USER, WebUtils.getUser(request));
		map.put(WebUtils.SYSTEM_USER, WebUtils.getSystemTime());
		// 查询列表
		if (tableAction.equals(DBUtils.TYPE_LIST)) {
			query.createSearchSql(map);
			mav.addAllObjects(map);
			mav.addObject("list", dao.list(query));
		}
		// 查询单个数据
		else if (tableAction.equals(DBUtils.TYPE_PAGE)) {
			PageBean page = new PageBean();
			Object o = map.get(PageBean.PAGING_CURRENT_PAGE);
			page.setCurrentPage((o != null) ? Integer.parseInt(o.toString()) : 0);
			o = map.get(PageBean.PAGING_PAGE_SIZE);
			page.setpageSize((o != null) ? Integer.parseInt(o.toString()) : 0);
			query.setPage(page);
			query.createSearchSql(map);
			dao.list(query);
			mav.addAllObjects(map);
			mav.addObject("page", page);
			// 查询单个数据
		} else if (tableAction.equals(DBUtils.TYPE_LOAD)) {
			query.createLoadSql(map);
			mav.addAllObjects(map);
			mav.addObject("data", dao.load(query));
		}
		return mav;
	}

	/**
	 * 根据传入参数，执行数据库查询操作
	 * 1.参数sql和tableName这两个参数必须提供一个。
	 * 2.tableAction是数据库查询操作的几个常量，包括：load：查找单条记录；list：查找列表记录；page：分页查找列表记录；map：将查找结果根据主键存入Map类中；
	 * @param request        - Http请求
	 * @param service 		    - 数据库连接服务类
	 * @param sql			    - 执行数据库操作的查询语句
	 * @param tableName  - 需要执行数据库查询操作的数据库表名
	 * @param tableAction - 执行数据库查询操作的分类
	 * @param jsp			    - 本操作执行完成后返回的JSP文件全路径名称
	 */
	@RequestMapping("/update.html")
	public ModelAndView update(HttpServletRequest request, Service service, String tableName, String tableAction, String jsp) {
		if (tableName == null || tableName.equals("")) {
			throw new SystemException("Action参数缺失！，tableName不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		if (tableAction == null || tableAction.equals("")) {
			throw new SystemException("Action参数缺失！，tableAction不能为空。", SystemErrorCode.A_PRARAMTER_LOST_ERROR);
		}
		FormConvert form = new FormConvert();
		Map<String, Object> map = form.convertRequest(request);
		TableMetaBean meta = DataBaseService.getService().getTable(tableName);
		String pk = meta.getPKFieldBean().getName();
		QueryMapSQL query = new QueryMapSQL(service);
		GenericDAO dao = new GenericDAO(service);
		map.put(QueryMapSQL.DEF_SYS_TABLE, tableName);
		map.put(WebUtils.SYSTEM_USER, WebUtils.getUser(request));
		map.put(WebUtils.SYSTEM_USER, WebUtils.getSystemTime());
		// 保存数据库操作(包括插入和更新)
		if (tableAction.equals(DBUtils.TYPE_UPDATE)) {
			// 如果主键不存在
			if (map.get(pk) == null && map.get(tableName + '.' + pk) == null) {
				// 如果没有主键生成策略
				if (meta.getKeyGenerate() == null) {
					String message = meta.getText() + '(' + meta.getName() + ')' + "保存数据时没有主键值，也没有定义主键策略。";
					throw new SystemException(message, SystemErrorCode.D_SQL_UPDATE_CREATE_ERROR);
				}
				// 如果有主键生成策略
				else {
					map.put(pk, meta.getUID());
					query.createInsertSql(tableName, map);
				}
			}
			// 如果主键存在
			else {
				// 如果有主键生成策略
				if (meta.getKeyGenerate() != null) {
					// 更新
					query.createUpdateSql(tableName, map);
				}
				// 如果没有主键生成策略
				else {
					query.createLoadSql(map);
					Object bean = dao.load(query);
					// 如果数据库没有记录，那么新增
					if (bean == null) {
						query.createInsertSql(tableName, map);
					}
					// 如果数据库有记录，那么更新
					else {
						query.createUpdateSql(tableName, map);
					}
				}
			}
		}
		// 删除数据库操作
		else if (tableAction.equals(DBUtils.TYPE_DELETE)) {
			// 如果主键不存在
			if (map.get(pk) != null) {
				query.createDeleteSql(tableName, map);
			} else {
				String message = meta.getText() + '(' + meta.getName() + ')' + "删除数据时没有主键值，没办法执行删除操作。";
				throw new SystemException(message, SystemErrorCode.D_SQL_UPDATE_CREATE_ERROR);
			}
		}
		dao.update(query);
		service.commit();
		if (jsp ==null) {
			ModelAndView mav = new ModelAndView("ajaxDone");
			mav.addObject("statusCode", 200);
			mav.addObject("message", "操作成功！");
			mav.addObject("callbackType", true);
			Object obj = map.get("navTabId");
			if (obj != null) {
				mav.addObject("navTabId", obj);
			}
			obj = map.get("rel");
			if (obj != null) {
				mav.addObject("rel", obj);
			}
			obj = map.get("callbackType");
			if (obj != null) {
				mav.addObject("callbackType", obj);
			}
			obj = map.get("forwardUrl");
			if (obj != null) {
				mav.addObject("forwardUrl", obj);
			}
			return mav;
		}
		return new ModelAndView("redirect:" + jsp);
	}

}
